package com.yami.shop.im.socket;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.bean.app.dto.ShopCartItemDto;
import com.yami.shop.bean.model.User;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.Json;
import com.yami.shop.common.util.SpringContextUtils;
import com.yami.shop.im.bean.ImRecord;
import com.yami.shop.im.bo.ShopSessionInfo;
import com.yami.shop.im.bo.SysSessionInfo;
import com.yami.shop.im.constants.MsgType;
import com.yami.shop.im.param.MessageInfo;
import com.yami.shop.im.bo.UserSessionInfo;
import com.yami.shop.im.hanlder.SecurityHandler;
import com.yami.shop.im.service.ImRecordService;
import com.yami.shop.im.vo.Conversation;
import com.yami.shop.im.vo.MsgItem;
import com.yami.shop.security.api.model.YamiUser;
import com.yami.shop.service.ShopDetailService;
import com.yami.shop.service.UserService;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 用户收到的消息
 * 10,"无法获取用户信息"
 * 11,"账户已在别处登录，请刷新"
 * 12,"对方不在线"
 * 13, "内容格式有误"
 */
@ServerEndpoint("/im/websocket/user/{token}")
@Component
@Slf4j
public class UserWebSocketServer {

    /**
     * UUID为key
     */
    public static final ConcurrentHashMap<String, UserSessionInfo> USER_MAP = new ConcurrentHashMap<>(256);

    private static UserService userService;

    private static SecurityHandler securityHandler;

    private static ImRecordService imRecordService;


    public static void setApplicationContext(ApplicationContext applicationContext) {
        userService = applicationContext.getBean(UserService.class);
        securityHandler = applicationContext.getBean(SecurityHandler.class);
        imRecordService = applicationContext.getBean(ImRecordService.class);
    }
    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session,@PathParam("token") String token) throws IOException {
        log.info("创建连接");
        YamiUser user = securityHandler.getUser(token);
        if (user == null) {
            session.getBasicRemote().sendText(Json.toJsonString(ServerResponseEntity.fail(10,"无法获取用户信息")));
            return;
        }

        // 如果原来就有token
        UserSessionInfo oldUserSessionInfo = USER_MAP.get(user.getUserId());
        if (oldUserSessionInfo != null) {
            // 客户端收到301，关闭ws链接，弹出提示
            if (oldUserSessionInfo.getSession().isOpen()) {
                oldUserSessionInfo.getSession().getBasicRemote().sendText(Json.toJsonString(ServerResponseEntity.fail(11,"账户已在别处登录，请刷新")));
                oldUserSessionInfo.getSession().close();
            }
        }

        User dbUser = userService.getUserByUserId(user.getUserId());

        UserSessionInfo userSessionInfo = new UserSessionInfo();
        userSessionInfo.setUserId(user.getUserId());
        userSessionInfo.setPic(dbUser.getPic());
        userSessionInfo.setNickName(dbUser.getNickName());
        userSessionInfo.setSession(session);


        USER_MAP.put(user.getUserId(), userSessionInfo);
        session.getBasicRemote().sendText(Json.toJsonString(ServerResponseEntity.success()));
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session,@PathParam("token") String token) throws IOException {
        log.info("关闭连接");
        YamiUser user = securityHandler.getUser(token);
        if (user == null) {
            return;
        }
        USER_MAP.remove(user.getUserId());
    }

    /**
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session,@PathParam("token") String token, Throwable error) throws IOException {

        log.error("发生错误");
        error.printStackTrace();

        YamiUser user = securityHandler.getUser(token);
        if (user == null) {
            return;
        }
        USER_MAP.remove(user.getUserId());
    }

    /**
     * 收到客户端消息后调用的方法，该消息由用户发过来
     *
     * @param sourceMessage
     *            客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String sourceMessage,@PathParam("token") String token, Session session) throws IOException {
        if (StrUtil.isBlank(sourceMessage)) {
            session.getBasicRemote().sendText(Json.toJsonString(ServerResponseEntity.fail(13,"内容格式有误")));
            return;
        }

        MessageInfo messageInfo = Json.parseObject(sourceMessage, MessageInfo.class);
        if (messageInfo == null) {
            session.getBasicRemote().sendText(Json.toJsonString(ServerResponseEntity.fail(13,"内容格式有误")));
            return;
        }

        // from user info
        YamiUser user = securityHandler.getUser(token);
        if (user == null) {
            log.error("无法获取用户信息");
            session.getBasicRemote().sendText(Json.toJsonString(ServerResponseEntity.fail(10,"无法获取用户信息")));
            return;
        }
        log.info("sourceMessage: " + sourceMessage);
        Long bizId = Long.valueOf(messageInfo.getToId());
        UserSessionInfo userSessionInfo = USER_MAP.get(user.getUserId());
        // 判断用户是发送给商家客服还是平台客服
        if(Objects.equals(messageInfo.getSendType(),1)) {
            List<SysSessionInfo> sysInfoList = new ArrayList<>();
            List<ImRecord> imRecords = new ArrayList<>();
            Date date = new Date();
            ImRecord imRecord = new ImRecord();
            if(Objects.equals(bizId,0L) && !PlatformWebSocketServer.SYS_MAP.isEmpty()){
                String code = IdUtil.simpleUUID();
                // 如果是0表示用户第一次连接，需要发送给所有在线的平台管理员
                for (Long key : PlatformWebSocketServer.SYS_MAP.keySet()) {
                    SysSessionInfo sysSessionInfo = PlatformWebSocketServer.SYS_MAP.get(key);
                    // 对方不在线，
                    if (sysSessionInfo == null) {
                        continue;
                    }
                    // 保存聊天记录
                    imRecord = new ImRecord();
                    imRecord.setBizId(sysSessionInfo.getUserId());
                    imRecord.setSendType(1);
                    imRecord.setSource(0);
                    imRecord.setUserId(user.getUserId());
                    imRecord.setContent(messageInfo.getContent());
                    imRecord.setType(messageInfo.getMsgType());
                    imRecord.setCreateTime(date);
                    imRecord.setIsRead(0);
                    imRecord.setMassMsgCode(code);
                    imRecords.add(imRecord);
                    sysInfoList.add(sysSessionInfo);
                }
            }else if(!Objects.equals(bizId,0L) && Objects.nonNull(PlatformWebSocketServer.SYS_MAP.get(bizId))){
                SysSessionInfo sysSessionInfo = PlatformWebSocketServer.SYS_MAP.get(bizId);
                imRecord = new ImRecord();
                imRecord.setSendType(1);
                imRecord.setSource(0);
                imRecord.setBizId(bizId);
                imRecord.setUserId(user.getUserId());
                imRecord.setContent(messageInfo.getContent());
                imRecord.setType(messageInfo.getMsgType());
                imRecord.setIsRead(sysSessionInfo == null ? 0:1);
                imRecord.setCreateTime(date);
                imRecords.add(imRecord);
                sysInfoList.add(sysSessionInfo);
            }
            // 保存聊天记录
            if (CollectionUtils.isNotEmpty(imRecords)) {
                imRecordService.saveBatch(imRecords);
            }
            // 对方不在线
            if (CollectionUtils.isEmpty(sysInfoList)) {
                session.getBasicRemote().sendText(Json.toJsonString(ServerResponseEntity.fail(12)));
                return;
            }
            // 批量发送消息给在线的平台管理员,先找出对应的消息
            Map<Long, ImRecord> map = imRecords.stream().collect(Collectors.toMap(ImRecord::getBizId,im -> im));
            for (SysSessionInfo sysSessionInfo : sysInfoList) {
                ImRecord record = map.get(sysSessionInfo.getUserId());
                MsgItem msgItem = imRecordService.getMsgItemByPlatform(sysSessionInfo, userSessionInfo, record);
                // 发给商家前端聊天记录
                sysSessionInfo.getSession().getBasicRemote().sendText(Json.toJsonString(ServerResponseEntity.success(msgItem)));
            }
        }else{
            ShopSessionInfo shopSessionInfo = ShopWebSocketServer.SHOP_MAP.get(bizId);
            // 保存聊天记录
            ImRecord imRecord = new ImRecord();
            imRecord.setBizId(bizId);
            imRecord.setUserId(user.getUserId());
            imRecord.setContent(messageInfo.getContent());
            imRecord.setCreateTime(new Date());
            imRecord.setSource(0);
            imRecord.setSendType(2);
            imRecord.setType(messageInfo.getMsgType());
            imRecord.setIsRead(shopSessionInfo == null ? 0 : 1);
            imRecordService.save(imRecord);
            // 对方不在线，
            if (shopSessionInfo == null) {
                session.getBasicRemote().sendText(Json.toJsonString(ServerResponseEntity.fail(12)));
                return;
            }
            MsgItem msgItem = imRecordService.getMsgItem(shopSessionInfo, userSessionInfo, imRecord);

            // 发给商家前端聊天记录
            shopSessionInfo.getSession().getBasicRemote().sendText(Json.toJsonString(ServerResponseEntity.success(msgItem)));
        }
//        // 和某人的聊天历史记录
//        if (Objects.equals(MsgType.HISTORY.value(), msgType)) {
//            List<ImRecord> imRecords = imRecordService.listHistory(shopId, user.getUserId(), 20);
//            List<MsgItem> msgItems = new ArrayList<>();
//            for (ImRecord record : imRecords) {
//                MsgItem msgItem = imRecordService.getMsgItem(shopSessionInfo, userSessionInfo, record);
//                msgItems.add(msgItem);
//            }
//
//            // 发给前端聊天记录
//            session.getBasicRemote().sendText(Json.toJsonString(ServerResponseEntity.success(msgItems)));
//            // 看了和某人的聊天记录，将未读聊天记录变成已读
//            imRecordService.updateToRead(user.getUserId(), shopId, 1);
//            return;
//        }
//        // 看了和某人的聊天记录，将未读聊天记录变成已读
//        imRecordService.updateToRead(user.getUserId(), shopId, 1);

    }



    /**
     * 实现服务器主动推送
     */
    public static boolean sendMessage(String userId, MsgItem msgItem) {
        UserSessionInfo userSessionInfo = USER_MAP.get(userId);
        if (userSessionInfo == null) {
            return false;
        }
        try {
            userSessionInfo.getSession().getBasicRemote().sendText(Json.toJsonString(ServerResponseEntity.success(msgItem)));
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }


}
